package org.finesys.chat.core.base.client;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import org.finesys.ai.core.chat.AssistantMessage;
import org.finesys.ai.core.chat.ChatCompletionRequest;
import org.finesys.ai.core.chat.ChatCompletionResponse;
import org.finesys.ai.core.chat.Content;
import org.finesys.ai.core.chat.ContentType;
import org.finesys.ai.core.chat.FunctionCall;
import org.finesys.ai.core.chat.FunctionMessage;
import org.finesys.ai.core.chat.ImageDetail;
import org.finesys.ai.core.chat.ImageUrl;
import org.finesys.ai.core.chat.InputAudio;
import org.finesys.ai.core.chat.Message;
import org.finesys.ai.core.chat.SystemMessage;
import org.finesys.ai.core.chat.ToolCall;
import org.finesys.ai.core.chat.ToolMessage;
import org.finesys.ai.core.chat.ToolType;
import org.finesys.ai.core.chat.UserMessage;
import org.finesys.ai.core.completion.CompletionRequest;
import org.finesys.ai.core.completion.CompletionResponse;
import org.finesys.ai.core.embedding.EmbeddingRequest;
import org.finesys.ai.core.embedding.EmbeddingResponse;
import org.finesys.ai.core.image.GenerateImagesRequest;
import org.finesys.ai.core.image.GenerateImagesResponse;
import org.finesys.chat.core.base.chat.ChatContent;
import org.finesys.chat.core.base.chat.ChatFunctionCall;
import org.finesys.chat.core.base.chat.ChatMessage;
import org.finesys.chat.core.base.chat.ChatRequest;
import org.finesys.chat.core.base.chat.ChatToolCall;
import org.finesys.chat.core.base.factory.ChatModel;
import org.springframework.util.StringUtils;

import reactor.core.publisher.Flux;

/**
 * 抽象类，实现ChatClient接口
 */
public class ChatClientAbstract implements ChatClient {

    /**
     * 模型信息
     */
    private ChatModel chatModel;


    public ChatClientAbstract(ChatModel chatModel) {
        this.chatModel = chatModel;
    }

    @Override
    public String getKey() {
        return chatModel.getModelId();
    }


    @Override
    public void register(ChatModel chatModel) {
        this.chatModel = chatModel;
    }

    @Override
    public void updateKey(ChatModel chatModel) {
        this.chatModel = chatModel;
    }

    @Override
    public void unregister() {
        this.chatModel = null;
    }

    @Override
    public Flux<CompletionResponse> completion(ChatRequest chatRequest) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Flux<ChatCompletionResponse> chatCompletion(ChatRequest chatRequest) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Flux<GenerateImagesResponse> imageGeneration(ChatRequest chatRequest) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Flux<EmbeddingResponse> embedding(ChatRequest chatRequest) {
        throw new UnsupportedOperationException();
    }


    /**
     * 根据传入的聊天请求构建补全请求。
     *
     * @param chatRequest 聊天请求对象
     * @return 构建好的补全请求对象
     */
    public CompletionRequest buildCompletionRequest(ChatRequest chatRequest) {
        return CompletionRequest.builder()
                .model(chatRequest.getModel())
                .maxTokens(chatRequest.getMaxTokens())
                .temperature(chatRequest.getTemperature())
                .topP(chatRequest.getTopP())
                .n(chatRequest.getN())
                .stream(chatRequest.getStream())
                .stop(stopWords(chatRequest.getStopWords()))
                .presencePenalty(chatRequest.getPresencePenalty())
                .frequencyPenalty(chatRequest.getFrequencyPenalty())
                .logitBias(chatRequest.getLogitBias())
                .user(chatRequest.getUser())
                .prompt(chatRequest.getUserMessage())
                .build();
    }

    /**
     * 根据ChatRequest构建ChatCompletionRequest
     *
     * @param chatRequest ChatRequest对象
     * @return 构建后的ChatCompletionRequest对象
     */
    public ChatCompletionRequest buildChatCompletionRequest(ChatRequest chatRequest) {
        ChatCompletionRequest.Builder completionRequestBuilder = ChatCompletionRequest.builder()
                .model(chatRequest.getModel())
                .maxCompletionTokens(chatRequest.getMaxTokens())
                .temperature(chatRequest.getTemperature())
                .topP(chatRequest.getTopP())
                .n(chatRequest.getN())
                .stream(chatRequest.getStream())
                .stop(stopWords(chatRequest.getStopWords()))
                .presencePenalty(chatRequest.getPresencePenalty())
                .frequencyPenalty(chatRequest.getFrequencyPenalty())
                .logitBias(chatRequest.getLogitBias())
                .user(chatRequest.getUser());
        if (chatRequest.getMessages() != null) {
            completionRequestBuilder.messages(buildChatMessage(chatRequest.getMessages()));
        }
        if (StringUtils.hasText(chatRequest.getSystemMessage())) {
            completionRequestBuilder.addSystemMessage(chatRequest.getSystemMessage());
        }
        if (StringUtils.hasText(chatRequest.getAssistantMessage())) {
            completionRequestBuilder.addAssistantMessage(chatRequest.getAssistantMessage());
        }
        if (StringUtils.hasText(chatRequest.getUserMessage())) {
            completionRequestBuilder.addUserMessage(chatRequest.getUserMessage());
        }
        return completionRequestBuilder.build();
    }

    public List<Message> buildChatMessage(List<ChatMessage> messageList) {
        if (messageList == null || messageList.isEmpty()) {
            return null;
        }
        List<Message> messages = new ArrayList<>(messageList.size());
        messageList.stream().forEach(chatMessage -> {
            // 转换聊天角色为枚举类型
            String chatRole = chatMessage.getRole().name();
            //
            switch (chatRole) {
                case "system":
                    SystemMessage.Builder systemMessageBulider = SystemMessage.builder();
                    systemMessageBulider.name(chatMessage.getName());
                    systemMessageBulider.content(String.valueOf(chatMessage.getContent()));
                    messages.add(systemMessageBulider.build());
                    break;
                case "user":
                    UserMessage.Builder userMessageBulider = UserMessage.builder();
                    userMessageBulider.name(chatMessage.getName());
                    if (chatMessage.getChatContents() != null && chatMessage.getChatContents().size() > 0) {
                        List<ChatContent> chatContents = (List<ChatContent>) chatMessage.getChatContents();
                        userMessageBulider.content(chatContents.stream().map(m -> {
                            Content.Builder builder = Content.builder()
                                    .type(ContentType.valueOf(m.getType().name()));
                            if (StringUtils.hasText(m.getText())) {
                                builder.text(m.getText());
                            }
                            if (m.getImageUrl() != null) {
                                builder.imageUrl(builderImageUrl(m.getImageUrl()));
                            }
                            if (m.getInputAudio() != null) {
                                builder.inputAudio(builderInputAudio(m.getInputAudio()));
                            }
                            return builder.build();
                        }).collect(Collectors.toList()));
                    }
                    if (chatMessage.getContent() != null) {
                        userMessageBulider.content(String.valueOf(chatMessage.getContent()));
                    }
                    messages.add(userMessageBulider.build());
                    break;
                case "assistant":
                    AssistantMessage.Builder assistantMessageBulider = AssistantMessage.builder();
                    assistantMessageBulider.name(chatMessage.getName());
                    assistantMessageBulider.content(String.valueOf(chatMessage.getContent()));
                    if (chatMessage.getToolCalls() != null) {
                        assistantMessageBulider.toolCalls(builderToolCalls(chatMessage.getToolCalls()));
                    }
                    if (chatMessage.getFunctionCall() != null) {
                        assistantMessageBulider.functionCall(builderFunctionCall(chatMessage.getFunctionCall()));
                    }
                    messages.add(assistantMessageBulider.build());
                    break;
                case "tool":
                    ToolMessage.Builder toolMessageBulider = ToolMessage.builder();
                    toolMessageBulider.toolCallId(chatMessage.getToolCallId());
                    toolMessageBulider.content(String.valueOf(chatMessage.getContent()));
                    messages.add(toolMessageBulider.build());
                    break;
                case "function":
                    FunctionMessage.Builder functionMessageBulider = FunctionMessage.builder();
                    functionMessageBulider.name(chatMessage.getName());
                    functionMessageBulider.content(String.valueOf(chatMessage.getContent()));
                    messages.add(functionMessageBulider.build());
                    break;
            }
        });
        return messages;
    }

    private FunctionCall builderFunctionCall(ChatFunctionCall functionCall) {
        FunctionCall.Builder builder = FunctionCall.builder();
        builder.name(functionCall.getName());
        builder.arguments(functionCall.getArguments());
        return builder.build();
    }

    public List<ToolCall> builderToolCalls(List<ChatToolCall> toolCalls) {
        List<ToolCall> toolCallsList = new ArrayList<>();
        toolCalls.forEach(toolCall -> {
            ToolCall.Builder builder = ToolCall.builder();
            builder.id(toolCall.getId());
            builder.index(toolCall.getIndex());
            builder.function(builderFunctionCall(toolCall.getFunction()));
            builder.type(ToolType.valueOf(toolCall.getType().name()));
            toolCallsList.add(builder.build());
        });
        return toolCallsList;
    }

    private InputAudio builderInputAudio(org.finesys.chat.core.base.chat.InputAudio inputAudio) {
        InputAudio.Builder builder = InputAudio.builder();
        builder.data(inputAudio.getData());
        builder.format(inputAudio.getFormat());
        return builder.build();
    }

    private ImageUrl builderImageUrl(org.finesys.chat.core.base.chat.ImageUrl imageUrl) {
        ImageUrl.Builder builder = ImageUrl.builder();

        builder.url(imageUrl.getUrl());
        builder.detail(ImageDetail.valueOf(imageUrl.getDetail().getValue()));
        return builder.build();
    }


    /**
     * 根据ChatRequest构建ChatCompletionRequest
     *
     * @param chatRequest ChatRequest对象
     * @return 构建后的ChatCompletionRequest对象
     */
    public GenerateImagesRequest buildImagesCompletionRequest(ChatRequest chatRequest) {
        GenerateImagesRequest.Builder imageRequestBuilder = GenerateImagesRequest.builder()
                .model(chatRequest.getModel())
                .n(chatRequest.getN())
                .user(chatRequest.getUser())
                .prompt(chatRequest.getUserMessage())
                .size(chatRequest.getImageSize())
                .quality(chatRequest.getImageQuality())
                .style(chatRequest.getImageStyle())
                .responseFormat(chatRequest.getImageResponseFormat());
        return imageRequestBuilder.build();
    }

    /**
     * 根据ChatRequest构建ChatCompletionRequest
     *
     * @param chatRequest ChatRequest对象
     * @return 构建后的ChatCompletionRequest对象
     */
    public EmbeddingRequest buildEmbeddingRequest(ChatRequest chatRequest) {
        EmbeddingRequest.Builder imageRequestBuilder = EmbeddingRequest.builder()
                .model(chatRequest.getModel())
                .user(chatRequest.getUser())

                .dimensions(chatRequest.getDimensions());

        List<String> inputs = chatRequest.getInput();
        if (inputs == null) {
            inputs = new ArrayList<>();
        }
        //加入用户消息
        if (chatRequest.getUserMessage() != null) {
            inputs.add(chatRequest.getUserMessage());
        }
        imageRequestBuilder.input(inputs);
        return imageRequestBuilder.build();
    }


    /**
     * 将给定的停止词字符串转换为字符串列表
     *
     * @param stopwords 停止词字符串，用逗号分隔
     * @return 停止词列表，如果stopwords为空则返回null
     */
    public List<String> stopWords(String stopwords) {
        if (StringUtils.hasText(stopwords)) {
            return Arrays.asList(StringUtils.split(stopwords, ","));
        }
        return null;
    }
}
